package client;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;



public class Client {

	private String SERVER_HOST_ADDRESS1;
	private int HOST_PORT1;
	private SSLSocket socket1;
	private ClientBackendThread server;
	private GUIThread gThread;
	private Monitor monitor;
	private WriteCommands wThread;
	
	private final String truststore = "src/keystores/truststore_c";
	
	private String user;
	private String pass;
	
	/**
	 * Constructor that takes no parameters. Defaults the host addresses
	 * to 'localhost' and port to 1337
	 */
	public Client(){
		SERVER_HOST_ADDRESS1 = "localhost";
		HOST_PORT1 = 1337;
	}

	/**
	 * Constructor that initializes the server addresses to args
	 * @param args <addr1> <port1> <user> <pass>
	 */
	public Client(String[] args) {
		System.setProperty("javax.net.ssl.trustStore", truststore);
		System.setProperty("javax.net.ssl.trustStorePassword", "medical");
		try {
			SERVER_HOST_ADDRESS1 = args[0];
			HOST_PORT1 = Integer.parseInt(args[1]);
			user = args[2];
			pass = args[3];
		} catch (NumberFormatException e) {
			e.printStackTrace();
			System.out.println("Wrong type of arguments, use: <host1> <port1> <user> <pass>");
		}
	}

	/**
	 * Connects the client to the cameras at hard-coded host addresses/ports.
	 * Also activates the inner workings of the client back-end.
	 * 
	 * @return if the connections succeeded.
	 */
	public boolean performConnect() {
		try {
			SSLSocketFactory factory = null;
		    try {
			SSLContext ctx;
			KeyManagerFactory kmf;
			KeyStore ks;
			char[] passphrase = pass.toCharArray();//"passphrase".toCharArray();

			ctx = SSLContext.getInstance("TLS");
			kmf = KeyManagerFactory.getInstance("SunX509");
			ks = KeyStore.getInstance("JKS");

			ks.load(new FileInputStream(user), passphrase);//("src/samples/sockets/client/testkeys"), passphrase);

			kmf.init(ks, passphrase);
			ctx.init(kmf.getKeyManagers(), null, null);

			factory = ctx.getSocketFactory();
		    } catch (Exception e) {
			throw new IOException(e.getMessage());
		    }

		    socket1 = (SSLSocket)factory.createSocket(SERVER_HOST_ADDRESS1, HOST_PORT1);
		    //socket1.startHandshake();
		    //socket1 = new Socket(SERVER_HOST_ADDRESS1, HOST_PORT1);
			monitor = new Monitor();
			server = new ClientBackendThread(monitor, socket1);
			wThread = new WriteCommands(socket1.getOutputStream(), monitor);
			gThread = new GUIThread(monitor);
			server.start();
			wThread.start();
			gThread.start();
			return true;
		} catch (IOException e) {
			//System.out.println(CAMERA_HOST_ADDRESS1 + " " + HOST_PORT1 + " " + CAMERA_HOST_ADDRESS2 + " " + HOST_PORT2);
			
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Disconnects the client from the servers. To get images after this, a new
	 * connection is required.
	 * 
	 * @return
	 */
	public boolean performDisconnect() {
		if (server.unbindSocket()) {
			gThread.interrupt();
			wThread.interrupt();
			return true;
		}
		return false;
	}

	/**
	 * Main method for the client. Starts the GUI as well as the native backend.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		Client fccb = null;
		if (args.length != 4) {
			System.out.println("Wrong number of arguments, use: <host1> <port1> <user> <pass>");
			//fccb = new Client();
			System.exit(-1);
		} else {
			fccb = new Client(args);
		}
		fccb.performConnect();
	}
}
